
package de.swta.freezay.components;

import de.swta.freezay.FreezaySession;
import de.swta.freezay.admin.item.ItemView;
import de.swta.freezay.admin.itemPackage.PackageEditPanel;
import de.swta.freezay.database.JPAController;
import de.swta.freezay.database.controller.exceptions.IllegalOrphanException;
import de.swta.freezay.database.controller.exceptions.NonexistentEntityException;
import de.swta.freezay.database.wicketAdapter.PackageDataProviderAdmin;
import de.swta.freezay.database.dbEntities.Item;
import de.swta.freezay.database.dbEntities.ItemPackage;
import de.swta.freezay.database.dbEntities.Package;
import de.swta.freezay.database.wicketAdapter.PackageDataProviderUser;
import de.swta.freezay.user.orderPanel.OrderPanel;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.text.NumberFormatter;
import org.apache.wicket.AttributeModifier;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.markup.html.AjaxLink;
import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
import org.apache.wicket.extensions.markup.html.repeater.data.sort.ISortStateLocator;
import org.apache.wicket.extensions.markup.html.repeater.data.sort.OrderByBorder;
import org.apache.wicket.extensions.markup.html.repeater.util.SortableDataProvider;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.basic.MultiLineLabel;
import org.apache.wicket.markup.html.navigation.paging.PagingNavigator;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.markup.repeater.data.DataView;
import org.apache.wicket.markup.repeater.data.ListDataProvider;
import org.apache.wicket.model.AbstractReadOnlyModel;
import org.apache.wicket.validation.validator.RangeValidator;

/**
 * A Panel to display packa entities
 *
 * @author Jan Korreck
 * @author Christian Baeumer
 */
public final class PackageView extends Panel {

    /* A NumberFormatter to display the price in the right way */
    private static final NumberFormatter NUMBER_FORMATTER
            = new NumberFormatter(new DecimalFormat("####.##"));
    
    private final ModalWindow w;
    private final WebMarkupContainer theContainer;
    
    public PackageView(String id) {
        super(id);

        /* set up a modal window for interaction */
        w = new ModalWindow("modal");
        add(w);

        /* set up a markup container to render data changes */
        theContainer = new WebMarkupContainer("theContainer");

        /* init the package view */
        init();
    }

  
    private void init() {

        SortableDataProvider dataProvider = null;
        String actionLabel = "RESERVIERUNG";
        String newPackage = "";
        String countTableHead = "";

        /* set up in case of admin logged in or logged out */
        if (((FreezaySession) getSession()).isLoggedIn()) {
            dataProvider = new PackageDataProviderAdmin();
            actionLabel = "EDITIEREN";
            newPackage = "Neu...";
            countTableHead = " (Res)";
        } else {
            dataProvider = new PackageDataProviderUser();
        }

        /* add an action label */
        theContainer.add(new Label("actionLabel", actionLabel));

        /* adds an action link to add new packages. This link is only displayed
         * if the admin is logged in */
        add(new ActionPanel("addPackage", newPackage, new AjaxLink("select") {
            // <editor-fold defaultstate="collapsed" desc="new package behaviour">
            // Edit package
            @Override
            public void onClick(AjaxRequestTarget target) {
                // Paket ist nicht reserviert
                target.appendJavascript("Wicket.Window.unloadConfirmation = false;");
                w.setContent(new PackageEditPanel(w.getContentId(), 0, false) {

                    @Override
                    public void saveLink(AjaxRequestTarget target) {
                        w.close(target);
                        target.addComponent(theContainer);

                    }
                });

               final ModalWindow.CloseButtonCallback callb
                       = new ModalWindow.CloseButtonCallback() {

                    public boolean onCloseButtonClicked(AjaxRequestTarget target) {
                        ((PackageEditPanel) w.get(w.getContentId())).discardActPackage();
                        w.setCloseButtonCallback(null);
                        return true;
                    }
                };

                w.setCloseButtonCallback(callb);
                w.setTitle("Paket editieren");
                w.setInitialHeight(350);
                w.setInitialWidth(400);
                w.show(target);
            }
            // </editor-fold>
        }));

        /* the "real" package data view */
        final DataView<Package> packageView = new DataView<Package>("package",
                dataProvider, 5) {

            /* called for every data entry in the table */
            @Override
            protected void populateItem(
                   final org.apache.wicket.markup.repeater.Item<Package> item) {

                /* get the package to display */
                final Package p = item.getModelObject();

                /* add the package data to the table */
                item.add(new Label("Name", p.getName()));
                item.add(new MultiLineLabel("Description", ""
                        + p.getDescription()));
                item.add(new Label("Category", p.getCategory().getName()));
                item.add(new CountDownLabel("Validity", p.getValidity()));

                if (((FreezaySession) getSession()).isLoggedIn()) {
                    // <editor-fold defaultstate="collapsed" desc="special case: admin is logged in: count is clickable">
                    item.add(new ActionPanel("Count", "" + p.getCount() + " ("
                           + p.getMinimumCount() + ")", new AjaxLink("select") {

                        @Override
                        public void onClick(AjaxRequestTarget target) {
                            w.setCloseButtonCallback(null);
                            if (p.getPrice() != 0) {
                                /* only if the package contains items. */
                                    w.setContent(new TextInputPanel(w.getContentId(),
                                            new RangeValidator(p.getMinimumCount(),
                                            p.getMaximumCount()), p.getCount()) {

                                        @Override
                                        public void submitClicked(
                                                AjaxRequestTarget target, Object input) {

                                            p.setCount((Integer) input);

                                            try {
                                               JPAController.PackageJpaController.edit(p);
                                            } catch (IllegalOrphanException ex) {
                                               Logger.getLogger(
                                                        ItemView.class.getName()).log(
                                                        Level.SEVERE, null, ex);
                                            } catch (NonexistentEntityException ex) {
                                               Logger.getLogger(
                                                        ItemView.class.getName()).log(
                                                        Level.SEVERE, null, ex);
                                            } catch (Exception ex) {
                                               Logger.getLogger(
                                                        ItemView.class.getName())
                                                        .log(Level.SEVERE, null, ex);
                                            }

                                            target.addComponent(theContainer);
                                            w.close(target);
                                    }
                                });


                                w.setTitle("Anzahl editieren");
                                w.setInitialHeight(150);
                                w.setInitialWidth(200);
                                w.show(target);
                            } else {
                                  target.appendJavascript(
                                          "alert('Das Paket muss " +
                                          "Produkte enthalten!')");
                            }
                        }
                    }));
                    // </editor-fold>
                } else {
                    item.add(new Label("Count", "" + p.getAvailableCount()));
                }


                /* use helper to add the package items */
                PackageView.this.addItems(p.getItemPackageCollection(), item);

                /* format the price and add it */
                try {
                    String discountString = (p.getDiscount() != 0)
                            ? ("\n   -" + NUMBER_FORMATTER.valueToString(
                                    p.getDiscount()) + "%")
                            : ("");

                    item.add(new MultiLineLabel("Price", ""
                            + NUMBER_FORMATTER.valueToString(p.getPrice()) +
                            " €" + discountString));
                    
                } catch (ParseException ex) {
                    Logger.getLogger(PackageView.class.getName()).log(
                            Level.SEVERE, null, ex);
                }

                if (((FreezaySession) getSession()).isLoggedIn()) {
                    // <editor-fold defaultstate="collapsed" desc="admin logged in: add extended action panel to edit package data">

                    item.add(new ExtendedActionPanel("Action",
                            new AjaxLink("select1") {

                                // Edit package
                                @Override
                                public void onClick(AjaxRequestTarget target) {
                                    if (!p.isReserved()) {
                                        // Paket ist nicht reserviert
                                        target.appendJavascript("Wicket.Window."
                                                + "unloadConfirmation = false;");
                                        w.setContent(new PackageEditPanel(
                                                w.getContentId(), p.getId(),
                                                true) {

                                            @Override
                                            public void saveLink(
                                                    AjaxRequestTarget target) {
                                              w.close(target);
                                              target.addComponent(theContainer);
                                            }
                                        });

                                        w.setTitle("Paket editieren");
                                        w.setInitialHeight(350);
                                        w.setInitialWidth(400);
                                        w.show(target);
                                    } else {
                                        target.appendJavascript(
                                                "alert('Das Paket ist bereits "
                                                + "reserviert - keine Edtierung"
                                                + " möglich!')");
                                    }

                                }
                            }, "Editieren", new AjaxLink("select2") {

                        @Override
                        public void onClick(AjaxRequestTarget target) {
                            if (!p.isReserved()) {
                                target.appendJavascript("Wicket.Window."
                                        + "unloadConfirmation = false;");

                                w.setContent(new OptionContentPanel(
                                        w.getContentId()) {

                                    public void onSelect(
                                            AjaxRequestTarget target,
                                            String selection) {

                                        if (!JPAController.PackageJpaController
                                                .isUsed(p.getId())) {

                                            try {
                                                // zuerst die ItemPackages löschen
                                                List<ItemPackage> itemPackages
                                                        = p.getItemPackageCollection();
                                                for (ItemPackage actIp : itemPackages) {
                                                    JPAController.ItemPackageJpaController.destroy(actIp.getItemPackagePK());
                                                }

                                                JPAController.PackageJpaController.destroy(p.getId());
                                            } catch (IllegalOrphanException ex) {
                                                Logger.getLogger(ItemView.class.getName()).log(Level.SEVERE, null, ex);
                                            } catch (NonexistentEntityException ex) {
                                                Logger.getLogger(ItemView.class.getName()).log(Level.SEVERE, null, ex);
                                            }
                                            w.close(target);

                                            target.addComponent(theContainer);

                                        } else {
                                            error("Löschen nicht möglich! \n " +
                                                    "Das Paket wird bereits verwendet!");
                                        }
                                    }

                                    public void onCancel(AjaxRequestTarget target) {
                                        w.close(target);
                                    }
                                });

                                ((OptionContentPanel) w.get(
                                        w.getContentId())).setMessageText(
                                        "Wollen sie das Paket '" + p.getName() + "' wirklich löschen?");

                                w.setTitle("Artikel löschen");
                                w.setInitialHeight(200);
                                w.setInitialWidth(300);
                                w.show(target);
                            } else {
                                target.appendJavascript("alert('Das Paket ist bereits reserviert - Löschen möglich!')");
                            }
                        }
                    }, "Löschen"));
                    // </editor-fold>
                } else {
                    // <editor-fold defaultstate="collapsed" desc="else add reservation link ">
                    item.add(new ActionPanel("Action", "Reservieren",
                            new AjaxLink("select") {

                                @Override
                                public void onClick(AjaxRequestTarget target) {

                                    target.appendJavascript("Wicket.Window.unloadConfirmation = false;");

                                    w.setContent(new OrderPanel(w.getContentId(), p.getId(), w));
                                    w.setTitle("Bestellung best&auml;tigen");
                                    w.show(target);
                                    w.setInitialHeight(200);
                                    w.setInitialWidth(400);
                   
                                }
                            }
                    ));
                    // </editor-fold>
                }

                /* to display the rows in different background colors the
                 * "row-attribute" must be modified */
                item.add(new AttributeModifier("class", true,
                    new AbstractReadOnlyModel<String>() {

                        @Override
                        public String getObject() {
                            return (item.getIndex() % 2 == 1) ? "even" : "odd";
                        }
                    }
                ));
            }
        };


        /* to sort column name on click add a new OrderByBorder */
        theContainer.add(createOrderByBorder("orderByPackageName", "name",
                dataProvider, packageView));
        /* to sort column description on click add a new OrderByBorder */
        theContainer.add(createOrderByBorder("orderByPackageDescription", 
                "description", dataProvider, packageView));
        /* to sort column category on click add a new OrderByBorder */
        String catSort;
        if (((FreezaySession) getSession()).isLoggedIn()) {
             catSort = "category.name";
        } else {
            catSort = "category";
        }
        theContainer.add(createOrderByBorder("orderByPackageCategory",
                catSort, dataProvider, packageView));
        
        /* to sort column validity on click add a new OrderByBorder */
        theContainer.add(createOrderByBorder("orderByPackageValidity", 
                "validity", dataProvider, packageView));
        /* to sort column count on click add a new OrderByBorder */
        theContainer.add(createOrderByBorder("orderByPackageCount", "count",
                dataProvider, packageView).add(new Label("reserved",
                countTableHead)));
        /* to sort column price on click add a new OrderByBorder */
        theContainer.add(createOrderByBorder("orderByPackagePrice", "price",
                dataProvider, packageView));

        theContainer.setOutputMarkupId(true);
        theContainer.add(packageView);
        add(theContainer);

        /* add page navigator on top and bottom of the package table */
        add(new PagingNavigator("pagenavigation_top", packageView));
        add(new PagingNavigator("pagenavigation_bottom", packageView));
    }

    /**
     * Adds the items of the specified itemPackageList to the package view
     *
     * @param itemList the itemPackageList
     * @param item the ListItem
     */
    private final void addItems(final List<ItemPackage> itemList,
            final org.apache.wicket.markup.repeater.Item item) {
        // <editor-fold defaultstate="collapsed" desc="fill package view with items">
        /* receive items in this package and sort them by category */
        Collections.sort(itemList, new Comparator<ItemPackage>() {

            public int compare(ItemPackage o1, ItemPackage o2) {
                return o1.getItem().getCategory().getName().compareTo(
                        o2.getItem().getCategory().getName());
            }
        });

        item.add(new DataView<ItemPackage>("Items",
                new ListDataProvider(itemList)) {

            @Override
            protected void populateItem(
                    org.apache.wicket.markup.repeater.Item<ItemPackage> item) {

                Item i = item.getModelObject().getItem();
                item.add(new Label("Name", "" + i.getName()));
                item.add(new Label("Category",
                        i.getCategory().getName()));
                try {
                    item.add(new Label("Amount",
                        NUMBER_FORMATTER.valueToString(i.getAmount()) + " "
                        + i.getUnit().getName()));
                } catch (ParseException ex) {
                    Logger.getLogger(PackageView.class.getName()).log(
                            Level.SEVERE, null, ex);
                }
                item.add(new Label("Count", ""
                        + item.getModelObject().getItemCount()));
            }
        });
        // </editor-fold>
    }

    /**
     * Sets up a column for sorting
     *
     * @param id the markupID
     * @param table the tableId
     * @param sortStateLocator the sort state locator
     * @param view the dataview
     *
     * @return OrderByBorder to register for sorting behaviour
     */
    private final OrderByBorder createOrderByBorder(final String id,
            final String table, final ISortStateLocator sortStateLocator,
            final DataView<?> view) {

        return new OrderByBorder(id, table, sortStateLocator) {
            @Override
            protected void onSortChanged() {
                view.setCurrentPage(0);
            }
        };
    }
}

